/*
 * Copyright (C) 2012-2013 Michael L.R. Marques
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 
 * Contact: michaellrmarques@gmail.com
 */

package com.jm.jmsql.sql;

import com.jm.commons.components.editor.UndoRedoEvent;
import com.jm.commons.components.editor.UndoRedoListener;
import com.jm.commons.logging.LogSystem;
import com.jm.commons.models.AdvancedSpinnerNumberModel;
import com.jm.jmsql.models.DefinitionComboBoxModel;
import com.jm.jmsql.models.ResultSetTableModel;
import com.jm.jmsql.objects.Databases;
import com.jm.jmsql.objects.Definition;
import com.jm.jmsql.objects.events.DefinitionEvent;
import com.jm.jmsql.objects.events.DefinitionListener;
import com.jm.jmsql.sql.predictions.events.PredictionEvent;
import com.jm.jmsql.sql.predictions.events.PredictionListener;
import com.jm.jmsql.tabulation.TabPageHeader;
import com.jm.jmsql.utils.Constants;
import com.jm.jmsql.utils.Settings;
import com.jm.jmsql.xport.XPortManager;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.print.PrinterException;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import javax.swing.JFileChooser;
import javax.swing.JTabbedPane;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableColumn;

/**
 * 
 * 
 * @author Michael L.R. Marques
 */
public class SQLEditor extends javax.swing.JPanel implements TableModelListener, UndoRedoListener, DefinitionListener, PredictionListener {
    
    /**
     * 
     */
    public static final String NEW_SQL_EDITOR = "New.sql";
    
    /**
     * 
     */
    public static final int DEFAULT_PAGE_SIZE = 20;
    
    /**
     * 
     */
    private static final AdvancedSpinnerNumberModel DEFAULT_PAGE_NUMBER_MODEL = new AdvancedSpinnerNumberModel(0, 0, 0, 1);
    
    /**
     * 
     */
    private static final AdvancedSpinnerNumberModel DEFAULT_PAGE_SIZE_NUMBER_MODEL = new AdvancedSpinnerNumberModel(0, 0, DEFAULT_PAGE_SIZE, 1);
    
    /**
     * 
     */
    private SQLPredictions predictions = new SQLPredictions(this.codeEditor);
    
    /**
     * 
     */
    private boolean edited;
    
    /**
     * Creates new form JMEditor
     */
    public SQLEditor() {
        initComponents();
        this.predictions.addPredictionListener(this);
        this.codeEditor.setContentType("text/sql");
        this.codeEditor.setComponentPopupMenu(null);
        for (KeyListener listener : this.codeEditor.getKeyListeners()) {
            this.codeEditor.removeKeyListener(listener);
        }
        this.codeEditor.addUndoRedoListener(this);
        this.codeEditor.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                /*
                // Only begin predicting if the definition is connected
                if (cbxDefinitions.getSelectedItem() != null) {
                    final Definition definition = (Definition) cbxDefinitions.getSelectedItem();
                    if (((Definition) cbxDefinitions.getSelectedItem()).isConnected()) {
                        // 
                        if (predictions.isVisible() &&
                                Character.isLetterOrDigit(e.getKeyChar())) {
                            predictions.predict(codeEditor, definition);
                        } else {
                            if ((KeyEvent.VK_SPACE == e.getKeyCode() &&
                                    KeyEvent.CTRL_MASK == e.getModifiers()) ||
                                        KeyEvent.VK_PERIOD == e.getKeyCode()) {
                                predictions.predict(codeEditor, definition);
                            }
                        }
                    }
                }
                */
            }
        });
        this.spinnerPage.setModel(DEFAULT_PAGE_NUMBER_MODEL);
        this.spinnerPageSize.setModel(DEFAULT_PAGE_SIZE_NUMBER_MODEL);
        this.cbxDefinitions.setRenderer(new DefinitionComboBoxModel.DefinitionComboBoxCellRenderer());
    }
    
    /**
     * 
     * @param databases 
     */
    public SQLEditor(Databases databases) {
        this();
        this.cbxDefinitions.setModel(new DefinitionComboBoxModel(databases));
        for (Definition definition : databases.getDefinitions()) {
            definition.addDefinitionListener(this);
        }
        selectedDefinitionChanged(null);
    }
    
    /**
     * 
     * @param databases
     * @param definition 
     */
    public SQLEditor(Databases databases, Definition definition) {
        this();
        this.cbxDefinitions.setModel(new DefinitionComboBoxModel(databases, definition));
        for (Definition def : databases.getDefinitions()) {
            def.addDefinitionListener(this);
        }
        selectedDefinitionChanged(null);
    }
    
    /**
     * 
     * @param databases
     * @param sqlFile
     * @throws IOException 
     */
    public SQLEditor(Databases databases, File sqlFile) throws IOException {
        this(databases);
        this.codeEditor.setText(SQLFileOperations.get(sqlFile));
    }
    
    /**
     * 
     * @param databases
     * @param definition
     * @param sqlFile
     * @throws IOException 
     */
    public SQLEditor(Databases databases, Definition definition, File sqlFile) throws IOException {
        this(databases, definition);
        this.codeEditor.setText(SQLFileOperations.get(sqlFile));
    }
    
    /**
     * 
     * @param databases
     * @param definition
     * @param sql 
     */
    public SQLEditor(Databases databases, Definition definition, String sql) {
        this(databases, definition, sql, false);
    }
    
    /**
     * 
     * @param databases
     * @param definition
     * @param sql
     * @param execute 
     */
    public SQLEditor(Databases databases, Definition definition, String sql, boolean execute) {
        this(databases, definition);
        this.codeEditor.setText(sql);
        if (execute) {
            execute(sql);
        }
    }
    
    /**
     * 
     * @return 
     */
    public boolean canExecute() {
        return this.cbxDefinitions.getSelectedItem() != null;
    }
    
    /**
     * 
     * @param query 
     */
    public void setSQLQuery(String query) {
        this.codeEditor.setText(query);
    }
    
    /**
     * 
     * @return 
     */
    public String getSQLQuery() {
        return this.codeEditor.getText();
    }
    
    /**
     * 
     */
    public void execute() {
        execute(this.codeEditor.getSelectedText() != null &&
                    !this.codeEditor.getSelectedText().trim().isEmpty() ? this.codeEditor.getSelectedText() : this.codeEditor.getText());
    }
    
    /**
     * 
     * @param sql 
     */
    protected void execute(String sql) {
        // Check if a definition is selected
        if (this.cbxDefinitions.getSelectedItem() != null) {
            // Get the selected definition
            Definition definition = (Definition) this.cbxDefinitions.getSelectedItem();
            // Check if the definition is connected
            if (!definition.isConnected()) {
                // Connect the definition
                definition.connect();
            }
            // If connected try to execute the query
            if (definition.isConnected()) {
                for (String executableSQL : sql.split(Constants.SQL.DELIMETER)) {
                    if (executableSQL.isEmpty()) {
                        return;
                    }
                    try {
                        if (definition.execute(executableSQL)) {
                            ResultSetTableModel model = new ResultSetTableModel(definition);
                            this.tableResults.setModel(model);
                            this.spinnerPage.setModel(model.getTotalRows() == 0 ? DEFAULT_PAGE_NUMBER_MODEL : new AdvancedSpinnerNumberModel(1, 1, model.getPages(), 1));
                            this.spinnerPageSize.setModel(model.getTotalRows() == 0 ? DEFAULT_PAGE_SIZE_NUMBER_MODEL : new AdvancedSpinnerNumberModel(model.getPageSize(), 1, model.getTotalRows(), 1));
                            model.addTableModelListener(this);
                            model.fireTableChanged();
                        }
                    } catch (SQLException sqle) {
                        LogSystem.log(getClass(), getClass().getEnclosingMethod(), sql, sqle);
                        information(definition.getFullException(), true);
                    }
                }
            }
        }
    }
    
    /**
     * 
     */
    public void openSQLFile() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("Open SQL File...");
        fileChooser.setCurrentDirectory(Settings.getSQLLocation());
        fileChooser.setFileFilter(SQLFileOperations.SQLFileFilter.getInstance());
        fileChooser.setMultiSelectionEnabled(false);
        if (JFileChooser.APPROVE_OPTION == fileChooser.showOpenDialog(this)) {
            try {
                this.codeEditor.setText(SQLFileOperations.get(fileChooser.getSelectedFile()));
                getHeader().setText(fileChooser.getSelectedFile().getName());
                getHeader().setToolTipText(fileChooser.getSelectedFile().getAbsolutePath());
                getHeader().setEdited(false);
            } catch (IOException ioe) {
                LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Opening SQL File", ioe);
            }
            Settings.setSQLLocation(fileChooser.getCurrentDirectory());
        }
    }
    
    /**
     * 
     */
    public void saveSQLFile() {
        saveSQLFile(false);
    }
    
    /**
     * 
     * @param saveAs 
     */
    public void saveSQLFile(boolean saveAs) {
        if (this.edited &&
                getHeader() != null) {
            if (!saveAs &&
                    getHeader().getToolTipText() != null &&
                        new File(getHeader().getToolTipText()).exists()) {
                try {
                    File file = new File(getHeader().getToolTipText());
                    SQLFileOperations.set(file, this.codeEditor.getText());
                    getHeader().setText(file.getName());
                    getHeader().setToolTipText(file.getAbsolutePath());
                    setEdited(false);
                } catch (IOException ioe) {
                    LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Saving SQL File", ioe);
                }
            } else {
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setDialogTitle("Save SQL File...");
                fileChooser.setCurrentDirectory(new java.io.File("./"));
                fileChooser.setFileFilter(SQLFileOperations.SQLFileFilter.getInstance());
                fileChooser.setMultiSelectionEnabled(false);
                if (JFileChooser.APPROVE_OPTION == fileChooser.showSaveDialog(this)) {
                    try {
                        SQLFileOperations.set(fileChooser.getSelectedFile(), this.codeEditor.getText());
                        getHeader().setText(fileChooser.getSelectedFile().getName());
                        getHeader().setToolTipText(fileChooser.getSelectedFile().getAbsolutePath());
                        setEdited(false);
                    } catch (IOException ioe) {
                        LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Saving SQL File", ioe);
                    }
                }
            }
        }
    }
    
    /**
     * 
     * @return 
     */
    public boolean isEdited() {
        return this.edited;
    }
    
    /**
     * 
     * @param edited 
     */
    public void setEdited(boolean edited) {
        if (getHeader() != null) {
            if (this.edited != edited) {
                this.edited = edited;
                getHeader().setEdited(this.edited);
            }
        }
    }
    
    /**
     * 
     * @return 
     */
    public boolean canUndo() {
       return this.codeEditor.canUndo(); 
    }
    
    /**
     * 
     */
    public void undo() {
        this.codeEditor.undo();
    }
    
    /**
     * 
     * @return 
     */
    public boolean canRedo() {
        return this.codeEditor.canRedo(); 
    }
    
    /**
     * 
     */
    public void redo() {
        this.codeEditor.redo();
    }
    
    /**
     * 
     */
    public void cut() {
        this.codeEditor.cut();
    }
    
    /**
     * 
     */
    public void copy() {
        this.codeEditor.copy();
    }
    
    /**
     * 
     */
    public void paste() {
        this.codeEditor.paste();
    }
    
    /**
     * 
     * @return 
     */
    public boolean canExport() {
        if (this.tableResults.getModel() instanceof ResultSetTableModel) {
            return ((ResultSetTableModel) this.tableResults.getModel()).getTotalRows() > 0;
        } else return false;
    }
    
    /**
     * 
     */
    public void export() {
        final XPortManager xportManager = new XPortManager(this);
        xportManager.setResultSet(((ResultSetTableModel) this.tableResults.getModel()).getResults());
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                xportManager.setVisible(true);
            }
        });
    }
    
    /**
     * 
     */
    public void find() {
        
    }
    
    /**
     * 
     */
    public void replace() {
        
    }
    
    /**
     * 
     * @throws PrinterException 
     */
    public void printSQL() throws PrinterException {
        this.codeEditor.print();
    }
    
    /**
     * 
     * @throws PrinterException 
     */
    public void printInformation() throws PrinterException {
        this.txtInformation.print();
    }
    
    /**
     * 
     */
    public void selectAllText() {
       this.codeEditor.selectAll(); 
    }
    
    /**
     * 
     * @param info
     * @param show 
     */
    private void information(String info, boolean show) {
        this.txtInformation.setText(this.txtInformation.getText().trim() + System.getProperty("line.separator") + info);
        if (show) {
            this.tabPane.setSelectedComponent(this.informationPanel);
        }
    }
    
    /**
     * 
     * @param e 
     */
    @Override public void undoPerformed(UndoRedoEvent e) {
        this.btnUndo.setEnabled(e.getUndo());
        this.btnRedo.setEnabled(e.getRedo());
    }
    
    /**
     * 
     * @param e 
     */
    @Override public void redoPerformed(UndoRedoEvent e) {
        this.btnUndo.setEnabled(e.getUndo());
        this.btnRedo.setEnabled(e.getRedo());
    }
    
    /**
     * 
     * @param e 
     */
    @Override public void changePerformed(UndoRedoEvent e) {
        this.btnUndo.setEnabled(e.getUndo());
        this.btnRedo.setEnabled(e.getRedo());
        setEdited(true);
    }
    
    /**
     * 
     * @param e 
     */
    @Override public void tableChanged(TableModelEvent e) {
        // Apply text information
        this.lblRows.setText("Total Rows: " + ((ResultSetTableModel) e.getSource()).getTotalRows());
        this.lblColumns.setText("Total Columns: " + ((ResultSetTableModel) e.getSource()).getTotalColumns());
        this.lblTotalPages.setText("Pages: " + ((ResultSetTableModel) e.getSource()).getPages());
        // Apply enabled/disabled buttons
        this.btnExport.setEnabled(((ResultSetTableModel) e.getSource()).getTotalRows() > 0);
        this.btnRefreshPage.setEnabled(true);
        this.btnFirstPage.setEnabled(!((ResultSetTableModel) e.getSource()).isFirstPage());
        this.btnPreviousPage.setEnabled(((ResultSetTableModel) e.getSource()).hasPreviousPage());
        this.btnNextPage.setEnabled(((ResultSetTableModel) e.getSource()).hasNextPage());
        this.btnLastPage.setEnabled(!((ResultSetTableModel) e.getSource()).isLastPage());
        this.spinnerPage.setEnabled(true);
        this.spinnerPage.setValue(((ResultSetTableModel) e.getSource()).getPage());
        this.spinnerPageSize.setEnabled(true);
        this.spinnerPageSize.setValue(((ResultSetTableModel) e.getSource()).getPageSize());
        // Adjust Number Column
        if (((ResultSetTableModel) e.getSource()).getRowCount() > 1) {
            TableColumn column = this.tableResults.getTableHeader().getColumnModel().getColumn(0);
            column.setPreferredWidth(Math.max(this.tableResults.prepareRenderer(this.tableResults.getCellRenderer(((ResultSetTableModel) e.getSource()).getRowCount()-1, 0), ((ResultSetTableModel) e.getSource()).getRowCount()-1, 0).getPreferredSize().width, 0));
        }
        // Set the table's tooltip text
        this.tableResults.setToolTipText("<html><body>Total Rows: " + ((ResultSetTableModel) e.getSource()).getTotalRows() + "<br>" +
                                                        "Total Columns: " + ((ResultSetTableModel) e.getSource()).getTotalColumns() + "<br>" +
                                                            "Page Rows: " + ((ResultSetTableModel) e.getSource()).getRowCount() + "<br>" +
                                                                "Pages: " + ((ResultSetTableModel) e.getSource()).getPages() + "<br>" +
                                                                    "Page: " + ((ResultSetTableModel) e.getSource()).getPage() + "</body></html>");
        this.tableResults.updateUI();
        this.tabPane.setSelectedComponent(this.resultsPanel);
    }
    
    /**
     * 
     * @return 
     */
    @Override 
    public SQLEditor clone() {
        SQLEditor sqlEditor = new SQLEditor((Databases) ((Definition) this.cbxDefinitions.getSelectedItem()).getDatabase().getParent(),
                                                (Definition) this.cbxDefinitions.getSelectedItem(),
                                                    this.codeEditor.getText());
        return sqlEditor;
    }
    
    /**
     * 
     * @return 
     */
    private TabPageHeader getHeader() {
        if (getParent() instanceof JTabbedPane &&
                getParent() != null) {
            ((JTabbedPane) getParent()).setSelectedComponent(this);
            return (TabPageHeader) ((JTabbedPane) getParent()).getTabComponentAt(((JTabbedPane) getParent()).getSelectedIndex());
        }
        return null;
    }
    
    /**
     * 
     * @param e 
     */
    @Override 
    public void connecting(DefinitionEvent e) {}
    
    /**
     * 
     * @param e 
     */
    @Override
    public void connectionSuccessful(DefinitionEvent e) {
        information("Connected to Database: " + e.getDefinition().getName() + ", Time Taken (s): " + (e.getSpent()/1000.00), true);
        selectedDefinitionChanged(null);
    }
    
    /**
     * 
     * @param e 
     */
    @Override 
    public void connectionFailed(DefinitionEvent e) {
        information(e.getDefinition().getFullException(), true);
    }
    
    /**
     * 
     * @param e 
     */
    @Override 
    public void connected(DefinitionEvent e) {}
    
    /**
     * 
     * @param e 
     */
    @Override 
    public void disconnecting(DefinitionEvent e) {}
    
    /**
     * 
     * @param e 
     */
    @Override 
    public void disconnected(DefinitionEvent e) {
        information("Disconnected from Database: " + e.getDefinition().getName() + ", Time Taken (s): " + (e.getSpent()/1000.00), true);
        selectedDefinitionChanged(null);
    }
    
    /**
     * 
     * @param e 
     */
    @Override 
    public void executing(DefinitionEvent e) { }
    
    /**
     * 
     * @param e 
     */
    @Override 
    public void executed(DefinitionEvent e) {
        if (e.getHasResults()) {
            information("Fetched Records: " + e.getDefinition().getRowCount() + ", Time Taken (s): " + (e.getSpent()/1000.00), false);
        } else {
            information("Updated Records: " + e.getDefinition().getUpdateCount() + ", Time Taken (s): " + (e.getSpent()/1000.00), true);
        }
    }
    
    /**
     * 
     * @param e 
     */
    @Override
    public void predicting(PredictionEvent e) {
        if (!this.predictions.isVisible()) {
            this.predictions.setLocation(codeEditor.getLocationOnScreen().x + codeEditor.getCaret().getMagicCaretPosition().x + 25, codeEditor.getLocationOnScreen().y + codeEditor.getCaret().getMagicCaretPosition().y + 25);
            this.predictions.setVisible(true);
        }
        this.codeEditor.requestFocusInWindow();
        this.codeEditor.requestFocus();
        
    }
    
    /**
     * 
     * @param e 
     */
    @Override
    public void predicted(PredictionEvent e) {
        this.codeEditor.requestFocusInWindow();
        this.codeEditor.requestFocus();
    }
    
    /**
     * 
     * @param e 
     */
    @Override
    public void predictionSelected(PredictionEvent e) {
        this.codeEditor.replaceSelection(e.getPrediction().getName());
    }
    
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainSplitPane = new javax.swing.JSplitPane();
        tabPane = new javax.swing.JTabbedPane();
        resultsPanel = new javax.swing.JPanel();
        jToolBar3 = new javax.swing.JToolBar();
        lblTotalPages = new javax.swing.JLabel();
        jSeparator10 = new javax.swing.JToolBar.Separator();
        lblPage = new javax.swing.JLabel();
        spinnerPage = new javax.swing.JSpinner();
        btnRefreshPage = new javax.swing.JButton();
        btnFirstPage = new javax.swing.JButton();
        btnPreviousPage = new javax.swing.JButton();
        btnNextPage = new javax.swing.JButton();
        btnLastPage = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JToolBar.Separator();
        jLabel1 = new javax.swing.JLabel();
        spinnerPageSize = new javax.swing.JSpinner();
        jSeparator2 = new javax.swing.JToolBar.Separator();
        lblRows = new javax.swing.JLabel();
        jSeparator7 = new javax.swing.JToolBar.Separator();
        lblColumns = new javax.swing.JLabel();
        jSeparator11 = new javax.swing.JToolBar.Separator();
        btnExport = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        tableResults = new javax.swing.JTable();
        informationPanel = new javax.swing.JPanel();
        jToolBar1 = new javax.swing.JToolBar();
        btnClearInformation = new javax.swing.JButton();
        btnPrintInformation = new javax.swing.JButton();
        scpInformation = new javax.swing.JScrollPane();
        txtInformation = new javax.swing.JTextPane();
        jScrollPane3 = new javax.swing.JScrollPane();
        codeEditor = new com.jm.commons.components.editor.JMEditorPane();
        jToolBar2 = new javax.swing.JToolBar();
        cbxDefinitions = new javax.swing.JComboBox();
        btnConnect = new javax.swing.JButton();
        btnDisconnect = new javax.swing.JButton();
        jSeparator3 = new javax.swing.JToolBar.Separator();
        btnPlay = new javax.swing.JButton();
        btnOpen = new javax.swing.JButton();
        btnSave = new javax.swing.JButton();
        jSeparator4 = new javax.swing.JToolBar.Separator();
        btnUndo = new javax.swing.JButton();
        btnRedo = new javax.swing.JButton();
        jSeparator5 = new javax.swing.JToolBar.Separator();
        btnCut = new javax.swing.JButton();
        btnCopy = new javax.swing.JButton();
        btnPaste = new javax.swing.JButton();
        jSeparator9 = new javax.swing.JToolBar.Separator();
        btnPrint = new javax.swing.JButton();

        mainSplitPane.setDividerLocation(125);
        mainSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        mainSplitPane.setOneTouchExpandable(true);

        tabPane.setToolTipText("");
        tabPane.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N

        jToolBar3.setFloatable(false);
        jToolBar3.setRollover(true);

        lblTotalPages.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        lblTotalPages.setText("Pages: 0");
        jToolBar3.add(lblTotalPages);
        jToolBar3.add(jSeparator10);

        lblPage.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        lblPage.setText("Page:");
        jToolBar3.add(lblPage);

        spinnerPage.setEnabled(false);
        spinnerPage.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                spinnerPageStateChanged(evt);
            }
        });
        jToolBar3.add(spinnerPage);

        btnRefreshPage.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/refresh_results.png"))); // NOI18N
        btnRefreshPage.setToolTipText("Refresh Results");
        btnRefreshPage.setEnabled(false);
        btnRefreshPage.setFocusable(false);
        btnRefreshPage.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnRefreshPage.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnRefreshPage.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                refresh(evt);
            }
        });
        jToolBar3.add(btnRefreshPage);

        btnFirstPage.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/first_results.png"))); // NOI18N
        btnFirstPage.setToolTipText("Go to First Page");
        btnFirstPage.setEnabled(false);
        btnFirstPage.setFocusable(false);
        btnFirstPage.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnFirstPage.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnFirstPage.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                firstPage(evt);
            }
        });
        jToolBar3.add(btnFirstPage);

        btnPreviousPage.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/previous_results.png"))); // NOI18N
        btnPreviousPage.setToolTipText("Previous Page");
        btnPreviousPage.setEnabled(false);
        btnPreviousPage.setFocusable(false);
        btnPreviousPage.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnPreviousPage.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnPreviousPage.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                previousPage(evt);
            }
        });
        jToolBar3.add(btnPreviousPage);

        btnNextPage.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/next_results.png"))); // NOI18N
        btnNextPage.setToolTipText("Next Page");
        btnNextPage.setEnabled(false);
        btnNextPage.setFocusable(false);
        btnNextPage.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnNextPage.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnNextPage.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nextPage(evt);
            }
        });
        jToolBar3.add(btnNextPage);

        btnLastPage.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/last_results.png"))); // NOI18N
        btnLastPage.setToolTipText("Go to Last Page");
        btnLastPage.setEnabled(false);
        btnLastPage.setFocusable(false);
        btnLastPage.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnLastPage.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnLastPage.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                lastPage(evt);
            }
        });
        jToolBar3.add(btnLastPage);
        jToolBar3.add(jSeparator1);

        jLabel1.setText("Rows: ");
        jToolBar3.add(jLabel1);

        spinnerPageSize.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        spinnerPageSize.setToolTipText("Number of Rows Per Page");
        spinnerPageSize.setEnabled(false);
        spinnerPageSize.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                pageSizeChanged(evt);
            }
        });
        jToolBar3.add(spinnerPageSize);
        jToolBar3.add(jSeparator2);

        lblRows.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        lblRows.setText("Total Rows: 0");
        jToolBar3.add(lblRows);
        jToolBar3.add(jSeparator7);

        lblColumns.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        lblColumns.setText("Total Columns: 0");
        jToolBar3.add(lblColumns);
        jToolBar3.add(jSeparator11);

        btnExport.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/xport.png"))); // NOI18N
        btnExport.setToolTipText("XPort Results... (Shift+Ctrl+X)");
        btnExport.setEnabled(false);
        btnExport.setFocusable(false);
        btnExport.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnExport.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnExport.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnExportActionPerformed(evt);
            }
        });
        jToolBar3.add(btnExport);

        tableResults.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        tableResults.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {

            }
        ));
        tableResults.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
        tableResults.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                rowSelected(evt);
            }
        });
        jScrollPane1.setViewportView(tableResults);

        javax.swing.GroupLayout resultsPanelLayout = new javax.swing.GroupLayout(resultsPanel);
        resultsPanel.setLayout(resultsPanelLayout);
        resultsPanelLayout.setHorizontalGroup(
            resultsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jToolBar3, javax.swing.GroupLayout.DEFAULT_SIZE, 696, Short.MAX_VALUE)
            .addGroup(resultsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 696, Short.MAX_VALUE))
        );
        resultsPanelLayout.setVerticalGroup(
            resultsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(resultsPanelLayout.createSequentialGroup()
                .addComponent(jToolBar3, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 283, Short.MAX_VALUE))
            .addGroup(resultsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, resultsPanelLayout.createSequentialGroup()
                    .addGap(26, 26, 26)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 282, Short.MAX_VALUE)))
        );

        tabPane.addTab("Results", new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/results.png")), resultsPanel, "SQL Results"); // NOI18N

        jToolBar1.setFloatable(false);
        jToolBar1.setRollover(true);

        btnClearInformation.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/clear.png"))); // NOI18N
        btnClearInformation.setFocusable(false);
        btnClearInformation.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnClearInformation.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnClearInformation.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                clearInformation(evt);
            }
        });
        jToolBar1.add(btnClearInformation);

        btnPrintInformation.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/printer.png"))); // NOI18N
        btnPrintInformation.setFocusable(false);
        btnPrintInformation.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnPrintInformation.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnPrintInformation.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                printInformation(evt);
            }
        });
        jToolBar1.add(btnPrintInformation);

        scpInformation.setViewportView(txtInformation);

        javax.swing.GroupLayout informationPanelLayout = new javax.swing.GroupLayout(informationPanel);
        informationPanel.setLayout(informationPanelLayout);
        informationPanelLayout.setHorizontalGroup(
            informationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 696, Short.MAX_VALUE)
            .addComponent(scpInformation)
        );
        informationPanelLayout.setVerticalGroup(
            informationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(informationPanelLayout.createSequentialGroup()
                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(scpInformation, javax.swing.GroupLayout.DEFAULT_SIZE, 277, Short.MAX_VALUE))
        );

        tabPane.addTab("Information", new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/information.png")), informationPanel, "Database SQL Information"); // NOI18N

        mainSplitPane.setRightComponent(tabPane);
        tabPane.getAccessibleContext().setAccessibleName("tabbedPane");

        jScrollPane3.setViewportView(codeEditor);

        mainSplitPane.setLeftComponent(jScrollPane3);

        jToolBar2.setFloatable(false);
        jToolBar2.setRollover(true);

        cbxDefinitions.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                selectedDefinitionChanged(evt);
            }
        });
        jToolBar2.add(cbxDefinitions);

        btnConnect.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/connected_definition.png"))); // NOI18N
        btnConnect.setToolTipText("Connect");
        btnConnect.setFocusable(false);
        btnConnect.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnConnect.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnConnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connect(evt);
            }
        });
        jToolBar2.add(btnConnect);

        btnDisconnect.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/disconnected_definition.png"))); // NOI18N
        btnDisconnect.setToolTipText("Disconnect");
        btnDisconnect.setFocusable(false);
        btnDisconnect.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnDisconnect.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnDisconnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                disconnect(evt);
            }
        });
        jToolBar2.add(btnDisconnect);
        jToolBar2.add(jSeparator3);

        btnPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/play.png"))); // NOI18N
        btnPlay.setToolTipText("Execute Query (F5)");
        btnPlay.setFocusable(false);
        btnPlay.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnPlay.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnPlay.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                executeQuery(evt);
            }
        });
        jToolBar2.add(btnPlay);

        btnOpen.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/open.png"))); // NOI18N
        btnOpen.setToolTipText("Open... (Ctrl+O)");
        btnOpen.setFocusable(false);
        btnOpen.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnOpen.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnOpen.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openSQLFile(evt);
            }
        });
        jToolBar2.add(btnOpen);

        btnSave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/save.png"))); // NOI18N
        btnSave.setToolTipText("Save (Ctrl+S)");
        btnSave.setFocusable(false);
        btnSave.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnSave.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveSQLFile(evt);
            }
        });
        jToolBar2.add(btnSave);
        jToolBar2.add(jSeparator4);

        btnUndo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/undo.png"))); // NOI18N
        btnUndo.setToolTipText("Undo (Ctrl+Z)");
        btnUndo.setEnabled(false);
        btnUndo.setFocusable(false);
        btnUndo.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnUndo.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnUndo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                undo(evt);
            }
        });
        jToolBar2.add(btnUndo);

        btnRedo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/redo.png"))); // NOI18N
        btnRedo.setToolTipText("Redo (Ctrl+Y)");
        btnRedo.setEnabled(false);
        btnRedo.setFocusable(false);
        btnRedo.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnRedo.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnRedo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                redo(evt);
            }
        });
        jToolBar2.add(btnRedo);
        jToolBar2.add(jSeparator5);

        btnCut.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/cut.png"))); // NOI18N
        btnCut.setToolTipText("Cut (Ctrl+X)");
        btnCut.setFocusable(false);
        btnCut.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnCut.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnCut.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cut(evt);
            }
        });
        jToolBar2.add(btnCut);

        btnCopy.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/copy.png"))); // NOI18N
        btnCopy.setToolTipText("Copy (Ctrl+C)");
        btnCopy.setFocusable(false);
        btnCopy.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnCopy.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnCopy.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                copy(evt);
            }
        });
        jToolBar2.add(btnCopy);

        btnPaste.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/paste.png"))); // NOI18N
        btnPaste.setToolTipText("Paste (Ctrl+V)");
        btnPaste.setFocusable(false);
        btnPaste.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnPaste.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnPaste.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                paste(evt);
            }
        });
        jToolBar2.add(btnPaste);
        jToolBar2.add(jSeparator9);

        btnPrint.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jm/jmsql/icons/printer.png"))); // NOI18N
        btnPrint.setToolTipText("Print (Ctrl+P)");
        btnPrint.setFocusable(false);
        btnPrint.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnPrint.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnPrint.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                print(evt);
            }
        });
        jToolBar2.add(btnPrint);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mainSplitPane)
            .addComponent(jToolBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jToolBar2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 475, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents
    
    /**
     * 
     * @param evt 
     */
    private void selectedDefinitionChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_selectedDefinitionChanged
        if (this.cbxDefinitions.getSelectedItem() != null) {
            this.btnConnect.setEnabled(!((Definition) this.cbxDefinitions.getSelectedItem()).isConnected());
            this.btnDisconnect.setEnabled(((Definition) this.cbxDefinitions.getSelectedItem()).isConnected());
        }
    }//GEN-LAST:event_selectedDefinitionChanged
    
    /**
     * 
     * @param evt 
     */
    private void connect(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connect
        if (this.cbxDefinitions.getSelectedItem() != null) {
            ((Definition) this.cbxDefinitions.getSelectedItem()).connect();
        }
    }//GEN-LAST:event_connect
    
    /**
     * 
     * @param evt 
     */
    private void disconnect(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_disconnect
        if (this.cbxDefinitions.getSelectedItem() != null) {
            ((Definition) this.cbxDefinitions.getSelectedItem()).disconnect();
        }
    }//GEN-LAST:event_disconnect
    
    /**
     * 
     * @param evt 
     */
    private void executeQuery(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_executeQuery
        execute();
    }//GEN-LAST:event_executeQuery
    
    /**
     * 
     * @param evt 
     */
    private void openSQLFile(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openSQLFile
        openSQLFile();
    }//GEN-LAST:event_openSQLFile
    
    /**
     * 
     * @param evt 
     */
    private void saveSQLFile(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveSQLFile
        saveSQLFile(getHeader().getText().equals(NEW_SQL_EDITOR));
    }//GEN-LAST:event_saveSQLFile
    
    /**
     * 
     * @param evt 
     */
    private void undo(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_undo
        undo();
    }//GEN-LAST:event_undo
    
    /**
     * 
     * @param evt 
     */
    private void redo(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_redo
        redo();
    }//GEN-LAST:event_redo
    
    /**
     * 
     * @param evt 
     */
    private void cut(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cut
        cut();
    }//GEN-LAST:event_cut
    
    /**
     * 
     * @param evt 
     */
    private void copy(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copy
        copy();
    }//GEN-LAST:event_copy
    
    /**
     * 
     * @param evt 
     */
    private void paste(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_paste
        paste();
    }//GEN-LAST:event_paste
    
    /**
     * 
     * @param evt 
     */
    private void pageSizeChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_pageSizeChanged
        try {
            ResultSetTableModel model = (ResultSetTableModel) this.tableResults.getModel();
            model.setPageSize(((Number) this.spinnerPageSize.getValue()).intValue());
            this.spinnerPage.setModel(model.getTotalRows() == 0 ? DEFAULT_PAGE_NUMBER_MODEL : new AdvancedSpinnerNumberModel(1, 1, model.getPages(), 1));
        } catch (SQLException sqle) {
            LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Page size changed", sqle);
            information(sqle.getMessage(), true);
        }
    }//GEN-LAST:event_pageSizeChanged
    
    /**
     * 
     * @param evt 
     */
    private void refresh(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refresh
        try {
            ((ResultSetTableModel) this.tableResults.getModel()).refresh();
        } catch (SQLException sqle) {
            LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Refresh result set", sqle);
            information(sqle.getMessage(), true);
        }
    }//GEN-LAST:event_refresh
    
    /**
     * 
     * @param evt 
     */
    private void firstPage(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_firstPage
        try {
            ((ResultSetTableModel) this.tableResults.getModel()).firstPage();
        } catch (SQLException sqle) {
            LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Move to first page", sqle);
            information(sqle.getMessage(), true);
        }
    }//GEN-LAST:event_firstPage
    
    /**
     * 
     * @param evt 
     */
    private void previousPage(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_previousPage
        try {
            ((ResultSetTableModel) this.tableResults.getModel()).previousPage();
        } catch (SQLException sqle) {
            LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Move to previous page", sqle);
            information(sqle.getMessage(), true);
        }
    }//GEN-LAST:event_previousPage
    
    /**
     * 
     * @param evt 
     */
    private void nextPage(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPage
        try {
            ((ResultSetTableModel) this.tableResults.getModel()).nextPage();
        } catch (SQLException sqle) {
            LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Move to next page", sqle);
            information(sqle.getMessage(), true);
        }
    }//GEN-LAST:event_nextPage
    
    /**
     * 
     * @param evt 
     */
    private void lastPage(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lastPage
        try {
            ((ResultSetTableModel) this.tableResults.getModel()).lastPage();
        } catch (SQLException sqle) {
            LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Move to last page", sqle);
            information(sqle.getMessage(), true);
        }
    }//GEN-LAST:event_lastPage
    
    /**
     * 
     * @param evt 
     */
    private void print(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_print
        try {
            printSQL();
        } catch (PrinterException pe) {
            LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Print SQL query", pe);
        }
    }//GEN-LAST:event_print
    
    /**
     * 
     * @param evt 
     */
    private void btnExportActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExportActionPerformed
        export();
    }//GEN-LAST:event_btnExportActionPerformed
    
    /**
     * 
     * @param evt 
     */
    private void rowSelected(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rowSelected
        if (evt.getClickCount() == 1 &&
                evt.getButton() == java.awt.event.MouseEvent.BUTTON3) {
            SQLEditorTablePopupMenu.show(this.tableResults, evt.getX(), evt.getY());
        } else if (evt.getClickCount() == 2 &&
                evt.getButton() == java.awt.event.MouseEvent.BUTTON1 &&
                    this.tableResults.getRowCount() > 0 &&
                        this.tableResults.getSelectedRow() >= 0 &&
                            this.tableResults.getColumnCount() > 0 &&
                                this.tableResults.getSelectedColumn() >= 0) {
            Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
            ClipboardOwner owner = new ClipboardOwner() {
                @Override public void lostOwnership(Clipboard clipboard, Transferable contents) {
                    // Do nothing
                }
            };
            clipboard.setContents(new StringSelection(this.tableResults.getValueAt(this.tableResults.getSelectedRow(), this.tableResults.getSelectedColumn()).toString().trim()), owner);
        }
    }//GEN-LAST:event_rowSelected
    
    /**
     * 
     * @param evt 
     */
    private void spinnerPageStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerPageStateChanged
        try {
            ((ResultSetTableModel) this.tableResults.getModel()).setPage(((Number) this.spinnerPage.getValue()).intValue());
        } catch (SQLException sqle) {
            LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Set the page number", sqle);
            information(sqle.getMessage(), true);
        }
    }//GEN-LAST:event_spinnerPageStateChanged
    
    /**
     * 
     * @param evt 
     */
    private void printInformation(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_printInformation
        try {
            printInformation();
        } catch (PrinterException pe) {
            LogSystem.log(getClass(), getClass().getEnclosingMethod(), "Print information", pe);
        }
    }//GEN-LAST:event_printInformation
    
    /**
     * 
     * @param evt 
     */
    private void clearInformation(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearInformation
        this.txtInformation.setText("");
    }//GEN-LAST:event_clearInformation
    
   
   
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnClearInformation;
    private javax.swing.JButton btnConnect;
    private javax.swing.JButton btnCopy;
    private javax.swing.JButton btnCut;
    private javax.swing.JButton btnDisconnect;
    private javax.swing.JButton btnExport;
    private javax.swing.JButton btnFirstPage;
    private javax.swing.JButton btnLastPage;
    private javax.swing.JButton btnNextPage;
    private javax.swing.JButton btnOpen;
    private javax.swing.JButton btnPaste;
    private javax.swing.JButton btnPlay;
    private javax.swing.JButton btnPreviousPage;
    private javax.swing.JButton btnPrint;
    private javax.swing.JButton btnPrintInformation;
    private javax.swing.JButton btnRedo;
    private javax.swing.JButton btnRefreshPage;
    private javax.swing.JButton btnSave;
    private javax.swing.JButton btnUndo;
    private javax.swing.JComboBox cbxDefinitions;
    private com.jm.commons.components.editor.JMEditorPane codeEditor;
    private javax.swing.JPanel informationPanel;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JToolBar.Separator jSeparator1;
    private javax.swing.JToolBar.Separator jSeparator10;
    private javax.swing.JToolBar.Separator jSeparator11;
    private javax.swing.JToolBar.Separator jSeparator2;
    private javax.swing.JToolBar.Separator jSeparator3;
    private javax.swing.JToolBar.Separator jSeparator4;
    private javax.swing.JToolBar.Separator jSeparator5;
    private javax.swing.JToolBar.Separator jSeparator7;
    private javax.swing.JToolBar.Separator jSeparator9;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JToolBar jToolBar2;
    private javax.swing.JToolBar jToolBar3;
    private javax.swing.JLabel lblColumns;
    private javax.swing.JLabel lblPage;
    private javax.swing.JLabel lblRows;
    private javax.swing.JLabel lblTotalPages;
    private javax.swing.JSplitPane mainSplitPane;
    private javax.swing.JPanel resultsPanel;
    private javax.swing.JScrollPane scpInformation;
    private javax.swing.JSpinner spinnerPage;
    private javax.swing.JSpinner spinnerPageSize;
    private javax.swing.JTabbedPane tabPane;
    private javax.swing.JTable tableResults;
    private javax.swing.JTextPane txtInformation;
    // End of variables declaration//GEN-END:variables
    
}
